package com.m3839.sdk.anti.core;

import android.app.Activity;

import com.m3839.sdk.anti.bean.AntiBean;
import com.m3839.sdk.anti.bean.LinkBean;
import com.m3839.sdk.anti.bean.PopConfigBean;
import com.m3839.sdk.anti.model.AntiApiModel;
import com.m3839.sdk.anti.model.IAntiModel;
import com.m3839.sdk.anti.ui.controller.AntiUiControllerImpl;
import com.m3839.sdk.anti.ui.controller.IAntiUiController;
import com.m3839.sdk.common.base.ResponseBean;
import com.m3839.sdk.common.core.Constant;
import com.m3839.sdk.common.core.SDKLifecycle;
import com.m3839.sdk.common.core.SdkConfiguration;
import com.m3839.sdk.common.event.SubjectBus;
import com.m3839.sdk.common.util.LogUtils;
import com.m3839.sdk.common.util.ResourcesUtils;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Observable;
import java.util.Observer;

/**
 * Description:HykbAntiManager
 *
 * @author 陈宝阳
 * @create 2020/8/4 11:39
 */
public class AntiManager {

    private static final int UNIT_HOUR = 60 * 60;

    /**
     * 用户不需要进行防沉迷限制
     */
    private static final int CODE_NOT_FCM = 100;

    /**
     * 用户需要防沉迷限制，返回剩余游戏时长，允许游戏
     */
    private static final int CODE_NEED_FCM_RETURN_TIME = 200;

    /**
     * 用户需要防沉迷限制，提醒用户限制游戏倒计时，允许游戏；
     */
    private static final int CODE_NEED_FCM_COUNT_TIME = 201;

    /**
     * 用户游戏时长剩余不足10分钟，建议客户端开启倒计时
     */
    private static final int CODE_FCM_START_COUNT_TIME = 202;

    /**
     * 用户需要防沉迷限制，弹窗提醒用户相关信息，禁止游戏；
     */
    private static final int CODE_BAN_GAME = 203;

    /**
     * 参数错误
     */
    private static final int CODE_PARAM_EXCEPTION = 401;

    /**
     * 心跳token异常
     */
    private static final int CODE_TOKEN_EXCEPTION = 402;

    /**
     * 心跳服务器异常
     */
    private static final int CODE_SERVER_EXCEPTION = 403;

    private final IAntiModel antiModel;

    private final IAntiUiController antiUiController;

    private AntiBean fcmConfig;

    private Activity activity;
    private String gameId;
    private String uid;
    private String nick;
    private String loginType;
    private String token;

    /**
     * 重试次数
     */
    private int retryCount = 0;

    private AntiManager() {
        antiModel = new AntiApiModel();
        antiUiController = new AntiUiControllerImpl();

        //该方法是距离游戏可玩时段的倒计时心跳回调
        SubjectBus.get().observe(Constant.HYKB_EVENT_ANTI_BEFORE, new Observer() {
            @Override
            public void update(Observable o, Object arg) {
                // 倒计时目前所剩余的时长
                int beforeStart = (int) arg;
                if (beforeStart == UNIT_HOUR) {
                    fcmConfig.resetToken();
                    checkFcm(gameId, uid, 0);
                } else {
                    antiUiController.updateAntiDialog(beforeStart);
                }
            }
        });

        // 倒计时候的悬浮气泡
        SubjectBus.get().observe(Constant.HYKB_EVENT_ANTI_COUNT_DOWN, new Observer() {
            @Override
            public void update(Observable o, Object arg) {
                PopConfigBean bean = (PopConfigBean) arg;
                if (bean.type == 2) {
                    //表示气泡
                    antiUiController.showFloatBubble(activity, bean.content, bean.linkBean);
                } else {
                    List<PopConfigBean> beans = new ArrayList<>();
                    beans.add(bean);
                    showFcmPop(beans);
                }
            }
        });

        //心跳请求
        SubjectBus.get().observe(Constant.HYKB_EVENT_ANTI_HEART, new Observer() {
            @Override
            public void update(Observable o, Object arg) {
                int second = (int) arg;
                checkFcm(gameId, uid, second);
            }
        });

        // 网络或者接口异常
        SubjectBus.get().observe(Constant.HYKB_EVENT_ANTI_LOAD_FAILED, new Observer() {
            @Override
            public void update(Observable o, Object arg) {
                handleError();
            }
        });

        // 防沉迷接口数据
        SubjectBus.get().observe(Constant.HYKB_EVENT_ANTI_LOAD_OK, new Observer() {
            @Override
            public void update(Observable o, Object arg) {
                try {
                    parseAntiData((String) arg);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    /**
     * 返回HykbAntiManager对象
     */
    public static AntiManager getInstance() {
        return SingletonHolder.INSTANCE;
    }

    private static class SingletonHolder {
        private static final AntiManager INSTANCE = new AntiManager();
    }

    /**
     * 心跳的数据请求
     */
    public void checkFcm(Activity activity, String userId, String nick, String loginType, String token) {
        LogUtils.flog("checkFcm");
        ResourcesUtils.setFontScale(activity);
        this.activity = activity;
        this.gameId = SdkConfiguration.getGameId();
        this.uid = userId;
        this.nick = nick;
        this.loginType = loginType;
        this.token = token;
        checkFcm(gameId, uid, 0);
        registerActivityLifecycleCallbacks();
    }

    /**
     * 心跳请求
     */
    public void onBeat() {
        checkFcm(gameId, uid, AntiHeartManager.getInstance().getCurrentSecond());
    }

    /**
     * 心跳数据请求
     */
    private void checkFcm(String gameId, String uid, long time) {
        try {
            antiModel.requestAntiData(gameId, uid, fcmConfig.getToken(), time);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 网络或者接口异常处理
     */
    public void handleError() {
        if (SdkConfiguration.getFcmStatus() == 1) {

            antiUiController.showNetTipDialog(activity);

            antiUiController.dismissAntiDialog();

            // 身份ID不为0 表示是已经在游戏中
            if (fcmConfig.getIdCardStatus() > 0 && retryCount < 2) {
                checkFcm(gameId, uid, 0);
                AntiBeforeHeartManager.getInstance().stopHeart();
                AntiHeartManager.getInstance().stopHeart();
                retryCount++;
            }
        } else {
            AntiHeartManager.getInstance().startHeart(fcmConfig.getInterval());
        }

    }

    /**
     * 解析防沉迷数据
     *
     */
    private void parseAntiData(String response) {

        ResponseBean<AntiBean> responseBean = new ResponseBean<>();
        responseBean.parse(response, true);
        fcmConfig = responseBean.getData();
        switch (responseBean.getCode()) {
            case CODE_NOT_FCM:
                handleNotAntiHeart();
                break;

            case CODE_NEED_FCM_RETURN_TIME:
            case CODE_NEED_FCM_COUNT_TIME:
                handleKeepHeart();
                break;

            case CODE_FCM_START_COUNT_TIME:
                handleCountDown();
                break;

            case CODE_BAN_GAME:
                handleBannedGame();
                break;

            case CODE_PARAM_EXCEPTION:
            case CODE_TOKEN_EXCEPTION:
            case CODE_SERVER_EXCEPTION:
                LogUtils.flog(responseBean.getMessage());
                handleError();
                break;
            default:
                break;
        }
    }

    /**
     * 不需要防沉迷心跳，正常游戏，针对code为100的情况
     */
    private void handleNotAntiHeart() {
        // 不做防沉迷，正常游戏
        AntiHeartManager.getInstance().stopHeart();
        AntiBeforeHeartManager.getInstance().stopHeart();
        stopCountDown();
        unregisterActivityLifecycleCallbacks();
        antiUiController.dismissFloatBubble();
        antiUiController.dismissAllDialog();
    }

    /**
     * 保持心跳,针对code为200或者201的情况
     */
    private void handleKeepHeart() {
        stopCountDown();
        // 做防沉迷持续心跳
        AntiHeartManager.getInstance()
                .setRemainingTime(fcmConfig.getRemainingTime(), getMoments());
        AntiHeartManager.getInstance().startHeart(fcmConfig.getInterval());
        antiUiController.dismissRealDialog();
    }

    /**
     * 执行倒计时操作,针对code为202的情况
     */
    private void handleCountDown() {
        stopCountDown();
        // 客户端做倒计时操作
        AntiHeartManager.getInstance()
                .setRemainingTime(fcmConfig.getRemainingTime(), getMoments());
        AntiHeartManager.getInstance().startCountDown();
        //做个判断是不是需要弹夜间的倒计时的弹窗
        if (fcmConfig.getPopConfigs().size() == 0 && fcmConfig.getCountDownBeans().size() == 0) {
            List<PopConfigBean> beans = new ArrayList<>();
            beans.add(fcmConfig.getOffLineBean());
            showFcmPop(beans);
        } else if (fcmConfig.getPopConfigs().size() == 0) {
            antiUiController.dismissRealDialog();
        } else {
            showFcmPop(fcmConfig.getPopConfigs());
        }
    }

    /**
     * 禁止游戏，针对code为203的情况
     */
    private void handleBannedGame() {
        //禁止游戏
        showFcmPop(fcmConfig.getPopConfigs());
        AntiHeartManager.getInstance().stopHeart();
        startCountDown();
        unregisterActivityLifecycleCallbacks();
    }

    /**
     * 倒计时气泡提醒时间点
     * @return
     */
    private List<PopConfigBean> getMoments() {
        List<PopConfigBean> countDownBeans = fcmConfig.getCountDownBeans();
        if (countDownBeans == null) {
            return new ArrayList<>();
        }
        //降序
        Collections.sort(countDownBeans, new Comparator<PopConfigBean>() {
            @Override
            public int compare(PopConfigBean o1, PopConfigBean o2) {
                return o2.moment - o1.moment;
            }
        });
        return countDownBeans;
    }

    /**
     * 显示气泡
     * @param tip 气泡文案
     * @param linkBean 气泡的链接
     */
    public void showFloatBubble(String tip, LinkBean linkBean) {
        antiUiController.showFloatBubble(activity, tip, linkBean);
    }

    /**
     * 启动倒计时，对距离可玩时间段的倒计时
     */
    public void startCountDown() {
        if (fcmConfig.getPopConfigs().size() > 0) {
            PopConfigBean bean = fcmConfig.getPopConfigs().get(0);
            int beforeStart = bean.beforeStart;
            AntiBeforeHeartManager.getInstance().setBeforeStart(beforeStart);
            AntiBeforeHeartManager.getInstance().startBeforeHeart();
        }
    }

    /**
     * 结束倒计时，对距离可玩时间段的倒计时
     */
    public void stopCountDown() {
        AntiBeforeHeartManager.getInstance().stopHeart();
        antiUiController.dismissAntiDialog();
    }

    /**
     * 防沉迷UI显示
     */
    public void showFcmPop(final List<PopConfigBean> beans) {
       antiUiController.showFcmPop(activity, beans, nick, uid, loginType);
    }

    public void stopFcm() {
        if (fcmConfig != null) {
            fcmConfig.resetToken();
        }
        AntiHeartManager.getInstance().stopHeart();
        unregisterActivityLifecycleCallbacks();
        antiUiController.dismissAllDialog();
    }

    public void resetToken() {
        if (fcmConfig != null) {
            fcmConfig.resetToken();
        }
    }

    private void registerActivityLifecycleCallbacks() {
        SDKLifecycle.install(activity, applicationStateCallback);
    }

    private void unregisterActivityLifecycleCallbacks() {
        SDKLifecycle.unInstall();
    }

    private SDKLifecycle.ApplicationStateCallback applicationStateCallback =
            new SDKLifecycle.ApplicationStateCallback() {

        @Override
        public void onActive() {
            AntiHeartManager.getInstance().startHeart(fcmConfig.getInterval());
        }

        @Override
        public void onInactive() {
            AntiHeartManager.getInstance().stopHeart();
        }
    };

    public void toRealNameWeb(Activity activity) {
        antiUiController.showRealNameDialog(activity, uid, loginType, token);
    }
}
